package com.cloud.logger.zchain.zchainclient.interceptor;

import com.cloud.logger.zchain.adapter.http.HttpServerRequestAdapter;
import com.cloud.logger.zchain.core.AbstractFilter;
import com.cloud.logger.zchain.core.ChainNode;
import com.cloud.logger.zchain.core.common.constant.UUIDGenerator;
import com.cloud.logger.zchain.core.common.entity.AngelaLoggerEntity;
import com.cloud.logger.zchain.core.common.entity.builder.AngelaLoggerEntityBuilder;
import com.cloud.logger.zchain.core.common.threadlocal.LoggerThreadLocal;
import com.cloud.logger.zchain.zchainclient.util.AngelaAopLogger;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashSet;
import java.util.Set;

/**
 * User: wcy
 * Date: 2017/4/14
 * Time: 9:55
 */
public class ZchainFilter extends AbstractFilter implements Filter {

    public static String ingoreUrl  = "multipart/form-data";

    public static String head = "HEAD";

    public static String OPTIONS = "OPTIONS";

    @Override
    public void destroy() {
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response,
                         FilterChain filterChain) throws IOException, ServletException {

        ChainNode chainNode = checkZchain((HttpServletRequest) request);

        if(chainNode !=null){
            LoggerThreadLocal.setLoggerId(chainNode.nodeId);
            LoggerThreadLocal.setNodeId(chainNode.nodeId);
        }else {
            String uuid = UUIDGenerator.getUuid();
            LoggerThreadLocal.setLoggerId(uuid);
            LoggerThreadLocal.setNodeId(uuid);
        }

        long startTime = System.currentTimeMillis();//开始时间

        HttpServletRequest httprequest = (HttpServletRequest) request;
        if (head.equals(httprequest.getMethod())||OPTIONS.equals(httprequest.getMethod())||ignore.contains(parseSuffix(httprequest.getRequestURL()))) {
            filterChain.doFilter(request, response);
        }
        else if(request.getContentType() != null && request.getContentType().contains(ingoreUrl)){
            //重写response
            WrapperResponse wrapperResponse = new WrapperResponse((HttpServletResponse) response);
            filterChain.doFilter(httprequest, wrapperResponse);
            //保存日志
            if(chainNode==null)
                collectIgnoreLogger(httprequest, wrapperResponse, startTime);

            ServletOutputStream out = response.getOutputStream();
            byte[] content = wrapperResponse.getContent();
            out.write(content);
            out.flush();
        }else{
            //重写response
            WrapperResponse wrapperResponse = new WrapperResponse((HttpServletResponse) response);
            //重写request
            MapRequestWrapper wrapperRequest = new MapRequestWrapper(httprequest);
            filterChain.doFilter(wrapperRequest, wrapperResponse);
            //保存日志
            if(chainNode==null)
                collectSimpleLogger(wrapperRequest, wrapperResponse, startTime);

            ServletOutputStream out = response.getOutputStream();
            byte[] content = wrapperResponse.getContent();
            out.write(content);
            out.flush();
        }

    }

    ChainNode checkZchain(HttpServletRequest request){
        return new HttpServerRequestAdapter(request,null).getChainNode();
    }

    private void collectSimpleLogger(MapRequestWrapper request, WrapperResponse response, long startTime) throws IOException {
        byte[] resultContent = response.getContent();
        String params = this.readJSONString(request);
        long endTime = System.currentTimeMillis();
        long elapsedTime = endTime - startTime;
        AngelaLoggerEntity logger = AngelaLoggerEntityBuilder.anAngelaLoggerEntity()
                .withResult(new String(resultContent, "utf-8"))
                .withMethod(request.getMethod())
                .withSourceIP(getIpAddress(request))
                .withElapsedTime(elapsedTime)
                .withInterfaceIp(String.valueOf(request.getRequestURL()+
                        (request.getQueryString()==null?"":("?"+request.getQueryString()))))
                .withInterfaceName(request.getRequestURI())
                .withParms(params)
                .withTenentId(request.getParameter("tenentId"))
                .withUuid(LoggerThreadLocal.getLoggerId()).build();
        AngelaAopLogger.loggerInterceptor(logger);
    }

    private void collectIgnoreLogger(HttpServletRequest request, WrapperResponse response, long startTime) throws IOException {
        byte[] resultContent = response.getContent();
        long endTime = System.currentTimeMillis();
        long elapsedTime = endTime - startTime;
        AngelaLoggerEntity logger = AngelaLoggerEntityBuilder.anAngelaLoggerEntity()
                .withResult(new String(resultContent, "utf-8"))
                .withMethod(request.getMethod())
                .withSourceIP(getIpAddress(request))
                .withElapsedTime(elapsedTime)
                .withInterfaceIp(String.valueOf(request.getRequestURL()+
                        (request.getQueryString()==null?"":("?"+request.getQueryString()))))
                .withInterfaceName(request.getRequestURI())
                .withTenentId(request.getParameter("tenentId"))
                .withUuid(LoggerThreadLocal.getLoggerId()).build();
        AngelaAopLogger.loggerInterceptor(logger);
    }


    @Override
    public void init(FilterConfig paramFilterConfig) throws ServletException {

    }

}
